home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / gcc / gcc258s.zoo / config / sh / sh.c next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  35.1 KB  |  1,638 lines

  1. /* Output routines for GCC for Hitachi Super-H
  2.    Copyright (C) 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. /* Contributed by Steve Chamberlain (sac@cygnus.com) */
  22.  
  23. #include <stdio.h>
  24. #include "assert.h"
  25. #include "config.h"
  26. #include "rtl.h"
  27. #include "regs.h"
  28. #include "hard-reg-set.h"
  29. #include "real.h"
  30. #include "insn-config.h"
  31. #include "conditions.h"
  32. #include "insn-flags.h"
  33. #include "tree.h"
  34. #include "output.h"
  35. #include "insn-attr.h"
  36. #include "flags.h"
  37. #include "obstack.h"
  38. #include "expr.h"
  39.  
  40.  
  41. static int add_constant ();
  42. int dump_constants ();
  43.  
  44. int current_function_anonymous_args;
  45. extern int current_function_pretend_args_size;
  46. extern char *version_string;
  47. extern int flag_traditional;
  48.  
  49.  
  50. enum attr_cpu sh_cpu;        /* target cpu */
  51.  
  52. /* Global variables for machine-dependent things. */
  53.  
  54. /* Saved operands from the last compare to use when we generate an scc
  55.   or bcc insn. */
  56.  
  57. rtx sh_compare_op0;
  58. rtx sh_compare_op1;
  59.  
  60. /* Provides the class number of the smallest class containing
  61.    reg number */
  62.  
  63. int regno_reg_class[FIRST_PSEUDO_REGISTER] =
  64. {
  65.   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  66.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  67.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  68.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  69.   GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, MAC_REGS,
  70.   MAC_REGS,
  71. };
  72.  
  73. /* Provide reg_class from a letter such as appears in the machine
  74.    description. */
  75.  
  76. enum reg_class reg_class_from_letter[] =
  77. {
  78.   /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
  79.   /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
  80.   /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
  81.   /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
  82.   /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
  83.   /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
  84.   /* y */ NO_REGS, /* z */ R0_REGS
  85. };
  86.  
  87.  
  88.  
  89.  
  90. /* Local label counter, used for constants in the pool and inside
  91.    pattern branches.  */
  92.  
  93. static int lf = 100;
  94.  
  95. /* Used to work out sizes of instructions */
  96. static int first_pc;
  97. static int pc;
  98. #define MAYBE_DUMP_LEVEL 900
  99. #define MUST_DUMP_LEVEL 1000
  100. static int dumpnext;
  101.  
  102.  
  103. void
  104. push (rn)
  105. {
  106.   emit_insn (gen_push (gen_rtx (REG, SImode, rn)));
  107. }
  108.  
  109. void
  110. pop (rn)
  111. {
  112.   emit_insn (gen_pop (gen_rtx (REG, SImode, rn)));
  113. }
  114.  
  115.  
  116. /* Adjust the stack and return the number of bytes taken to do it */
  117.  
  118. static void
  119. output_stack_adjust (direction, size)
  120.      int direction;
  121.      int size;
  122. {
  123.   if (size)
  124.     {
  125.       rtx val = GEN_INT (size);
  126.       rtx insn;
  127.  
  128.       if (size > 120)
  129.     {
  130.       rtx nval = gen_rtx (REG, SImode, 13);
  131.       emit_insn (gen_movsi (nval, val));
  132.       val = nval;
  133.     }
  134.  
  135.       if (direction > 0)
  136.     insn = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, val);
  137.       else
  138.     insn = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, val);
  139.  
  140.       emit_insn (insn);
  141.     }
  142. }
  143.  
  144.  
  145.  
  146. /* Generate code to push the regs specified in the mask, and return
  147.    the number of bytes the insns take. */
  148.  
  149. static void
  150. push_regs (mask)
  151.      int mask;
  152. {
  153.   int i;
  154.   int size = 0;
  155.  
  156.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  157.     {
  158.       if (mask & (1 << i))
  159.     {
  160.       push (i);
  161.     }
  162.     }
  163. }
  164.  
  165.  
  166. /*
  167.   Print an instruction which would have gone into a delay slot
  168.   after an instructiuon, but couldn't because the instruction expanded
  169.   into a sequence where putting the slot insn at the end wouldn't work.
  170.   */
  171.  
  172. void
  173. print_slot (insn)
  174.      rtx insn;
  175. {
  176.   final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1);
  177.  
  178.   INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
  179. }
  180.  
  181. /* Number of bytes pushed for anonymous args */
  182.  
  183. static int extra_push;
  184.  
  185. /* Work out the registers which need to be saved, both as a mask and a
  186.    count */
  187.  
  188. int
  189. calc_live_regs (count)
  190.      int *count;
  191. {
  192.   int reg;
  193.   int live_regs_mask = 0;
  194.   *count = 0;
  195.  
  196.   for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
  197.     {
  198.       if (regs_ever_live[reg] && !call_used_regs[reg])
  199.     {
  200.       (*count)++;
  201.       live_regs_mask |= (1 << reg);
  202.     }
  203.     }
  204.   return live_regs_mask;
  205. }
  206.  
  207.  
  208.  
  209.  
  210. static int
  211. need_slot (insn)
  212.      rtx insn;
  213. {
  214.   return (insn && !INSN_ANNULLED_BRANCH_P (XVECEXP (insn, 0, 0)));
  215. }
  216.  
  217. /* Print the operand address in x to the stream */
  218.  
  219. void
  220. print_operand_address (stream, x)
  221.      FILE *stream;
  222.      rtx x;
  223. {
  224.   switch (GET_CODE (x))
  225.     {
  226.     case REG:
  227.       fprintf (stream, "@%s", reg_names[REGNO (x)]);
  228.       break;
  229.     case PLUS:
  230.       {
  231.     rtx base = XEXP (x, 0);
  232.     rtx index = XEXP (x, 1);
  233.  
  234.     if (GET_CODE (base) != REG)
  235.       {
  236.         /* Ensure that BASE is a register (one of them must be). */
  237.         rtx temp = base;
  238.         base = index;
  239.         index = temp;
  240.       }
  241.  
  242.     switch (GET_CODE (index))
  243.       {
  244.       case CONST_INT:
  245.         fprintf (stream, "@(%d,%s)",
  246.              INTVAL (index),
  247.              reg_names[REGNO (base)]);
  248.         break;
  249.  
  250.       case REG:
  251.         fprintf (stream, "@(r0,%s)",
  252.              reg_names[MAX (REGNO (base), REGNO (index))]);
  253.  
  254.         break;
  255.  
  256.       default:
  257.         debug_rtx (x);
  258.  
  259.         abort ();
  260.       }
  261.       }
  262.  
  263.       break;
  264.     case PRE_DEC:
  265.       fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
  266.       break;
  267.  
  268.     case POST_INC:
  269.       fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
  270.       break;
  271.  
  272.     default:
  273.       output_addr_const (stream, x);
  274.       break;
  275.     }
  276. }
  277.  
  278. /* Print operand x (an rtx) in assembler syntax to file stream
  279.    according to modifier code.
  280.  
  281.    '.'  print a .s if insn needs delay slot
  282.    '*'  print a local label
  283.    '^'  increment the local label number
  284.    '!'  dump the constant table
  285.    '#'  output a nop if there is nothing to put in the delay slot
  286.    'R'  print the next register or memory location along, ie the lsw in
  287.    a double word value
  288.    'O'  print a constant without the #
  289.    'M'  print a constant as its negative
  290.    'I'  put something into the constant pool and print its label */
  291.  
  292. void
  293. print_operand (stream, x, code)
  294.      FILE *stream;
  295.      rtx x;
  296.      int code;
  297. {
  298.   switch (code)
  299.     {
  300.  
  301.  
  302.     case '.':
  303.       if (need_slot (final_sequence))
  304.     fprintf (stream, ".s");
  305.       break;
  306.     case '*':
  307.       fprintf (stream, "LF%d", lf);
  308.       break;
  309.     case '!':
  310.       dump_constants (0);
  311.       break;
  312.     case '^':
  313.       lf++;
  314.       break;
  315.  
  316.     case '#':
  317.       /* Output a nop if there's nothing in the delay slot */
  318.       if (dbr_sequence_length () == 0)
  319.     {
  320.       fprintf (stream, "\n\tor    r0,r0\t!wasted slot");
  321.     }
  322.       break;
  323.     case 'O':
  324.       fprintf (asm_out_file, "%d", INTVAL (x));
  325.       break;
  326.  
  327.     case 'I':
  328.       fprintf (asm_out_file, "LK%d", add_constant (x, SImode));
  329.       break;
  330.  
  331.     case 'M':
  332.       fprintf (asm_out_file, "#%d", -INTVAL (x));
  333.       break;
  334.  
  335.     case 'R':
  336.       /* Next location along in memory or register*/
  337.       switch (GET_CODE (x))
  338.     {
  339.     case REG:
  340.       fputs (reg_names[REGNO (x) + 1], (stream));
  341.       break;
  342.     case MEM:
  343.       print_operand_address (stream,
  344.                    XEXP (adj_offsettable_operand (x, 4), 0), 0);
  345.       break;
  346.     }
  347.       break;
  348.  
  349.     default:
  350.       switch (GET_CODE (x))
  351.     {
  352.     case REG:
  353.       fputs (reg_names[REGNO (x)], (stream));
  354.       break;
  355.     case MEM:
  356.       output_address (XEXP (x, 0));
  357.       break;
  358.     default:
  359.       fputc ('#', stream);
  360.       output_addr_const (stream, x);
  361.       break;
  362.  
  363.     }
  364.       break;
  365.     }
  366. }
  367.  
  368.  
  369.  
  370. /* Define the offset between two registers, one to be eliminated, and
  371.    the other its replacement, at the start of a routine.  */
  372.  
  373. int
  374. initial_elimination_offset (from, to)
  375. {
  376.   int regs_saved;
  377.   int d = calc_live_regs (®s_saved);
  378.   int total_saved_regs_space = (regs_saved) * 4;
  379.   int total_auto_space = get_frame_size ();
  380.  
  381.  
  382.   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
  383.     {
  384.       return total_saved_regs_space;
  385.     }
  386.  
  387.   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  388.     {
  389.       return total_saved_regs_space + total_auto_space;
  390.     }
  391.  
  392.   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  393.     {
  394.       return total_auto_space;
  395.     }
  396. }
  397.  
  398.  
  399. /* Prepare operands for a move define_expand; specifically, one of the
  400.    operands must be in a register.  Take this chance to remove
  401.    addressing modes which can't be coped with very well. */
  402.  
  403. int
  404. prepare_move_operands (operands, mode)
  405.      rtx operands[];
  406.      enum machine_mode mode;
  407. {
  408.   /* One of the operands has to be a register */
  409.   if ((!register_operand (operands[0], mode)
  410.        && !register_operand (operands[1], mode))
  411.       || GET_CODE (operands[1]) == PLUS)
  412.     {
  413.       /* copy the source to a register */
  414.       operands[1] = copy_to_mode_reg (mode, operands[1]);
  415.     }
  416.  
  417.   /* If we've got a negative index, break it down */
  418.  
  419.   if (GET_CODE (operands[0]) == MEM && !reload_in_progress)
  420.     {
  421.  
  422.       rtx inside = XEXP (operands[0], 0);
  423.       if (GET_CODE (inside) == PLUS)
  424.     {
  425.       rtx inside1 = XEXP (inside, 1);
  426.       if (GET_CODE (inside1) == CONST_INT
  427.           && INTVAL (inside1) < 0)
  428.         {
  429.           /* Catch this now and break it into bits, it will only cause
  430.          problems later */
  431.  
  432.           rtx sub = copy_to_mode_reg (SImode, inside);
  433.           XEXP (operands[0], 0) = sub;
  434.         }
  435.     }
  436.     }
  437.   return 0;
  438. }
  439.  
  440.  
  441. /* Prepare the operands for an scc instruction; make sure that the
  442.    compare has been done.  */
  443. rtx
  444. prepare_scc_operands (code)
  445. {
  446.   if (GET_CODE (sh_compare_op0) != REG
  447.       || REGNO (sh_compare_op0) != T_REG)
  448.     {
  449.       /* First need a compare insn */
  450.       emit_insn (gen_rtx (SET, SImode,
  451.               gen_rtx (REG, SImode, T_REG),
  452.               gen_rtx (code, SImode, sh_compare_op0,
  453.                    sh_compare_op1)));
  454.     }
  455.   return gen_rtx (REG, SImode, T_REG);
  456. }
  457.  
  458.  
  459. /* Functions to output assembly */
  460.  
  461. /* Return a sequence of instructions to perform DI or DF move.
  462.  
  463.    Since the SH cannot move a DI or DF in one instruction, we have
  464.    to take care when we see overlapping source and dest registers.
  465.  
  466.  */
  467. char *
  468. output_movedouble (operands, mode)
  469.      rtx operands[];
  470.      enum machine_mode mode;
  471. {
  472.   rtx dst = operands[0];
  473.   rtx src = operands[1];
  474.   int lowfirst;
  475.  
  476.   if (register_operand (dst, mode)
  477.       && register_operand (src, mode))
  478.     {
  479.       if (REGNO (src) == MACH_REG)
  480.     return "sts    mach,%0\n\tsts    macl,%R0";
  481.  
  482.       /*
  483.     when mov.d r1,r2 do r2->r3 then r1->r2
  484.     when mov.d r1,r0 do r1->r0 then r2->r1
  485.     */
  486.  
  487.       if (REGNO (src) + 1 == REGNO (dst))
  488.     return "mov    %1,%0\n\tmov    %R1,%R0 ! cr";
  489.       else
  490.     return "mov    %R1,%R0\n\tmov    %1,%0 ";
  491.  
  492.     }
  493.   else if (GET_CODE (src) == CONST_INT)
  494.     {
  495.       if (INTVAL (src) < 0)
  496.     return "mov    #-1,%0\n\tmov    %1,%R0";
  497.       else
  498.     return "mov    #0,%0\n\tmov    %1,%R0";
  499.     }
  500.  
  501.   else if (GET_CODE (src) == MEM)
  502.     {
  503.       int ptrreg1 = -1;
  504.       int ptrreg2 = -1;
  505.       int dreg = REGNO (dst);
  506.       rtx inside = XEXP (src, 0);
  507.  
  508.       if (GET_CODE (inside) == REG)
  509.     {
  510.       ptrreg1 = REGNO (inside);
  511.     }
  512.       else if (GET_CODE (inside) == PLUS)
  513.     {
  514.       rtx lhs = XEXP (inside, 0);
  515.       rtx rhs = XEXP (inside, 1);
  516.       if (GET_CODE (lhs) == REG)
  517.         ptrreg1 = REGNO (lhs);
  518.       if (GET_CODE (rhs) == REG)
  519.         ptrreg2 = REGNO (rhs);
  520.     }
  521.       else
  522.     abort ();
  523.  
  524.  
  525.       if ((ptrreg1 >= 0 && ptrreg2 >= 0)
  526.       && (dreg == ptrreg1
  527.           || dreg == ptrreg2
  528.           || dreg + 1 == ptrreg1
  529.           || dreg + 1 == ptrreg2))
  530.     {
  531.       /* This move clobbers both index registers,
  532.          calculate the sum in one register.  */
  533.       fprintf (asm_out_file, "    add    %s,%s ! special fix\n",
  534.            reg_names[ptrreg2], reg_names[ptrreg1]);
  535.  
  536.       if (dreg == ptrreg1)
  537.         {
  538.           /* Copy into dreg+1 first.  */
  539.           fprintf (asm_out_file, "    mov.l    @(4,%s),%s\n",
  540.                reg_names[ptrreg1],
  541.                reg_names[dreg + 1]);
  542.  
  543.           fprintf (asm_out_file, "    mov.l    @(%s),%s\n",
  544.                reg_names[ptrreg1],
  545.                reg_names[dreg]);
  546.         }
  547.       else
  548.         {
  549.           /* Copy into dreg first. */
  550.           fprintf (asm_out_file, "    mov.l    @(%s),%s\n",
  551.                reg_names[ptrreg1],
  552.                reg_names[dreg]);
  553.  
  554.           fprintf (asm_out_file, "    mov.l    @(4,%s),%s\n",
  555.                reg_names[ptrreg1],
  556.                reg_names[dreg + 1]);
  557.  
  558.         }
  559.       warning ("generated complex amode");
  560.       return "";
  561.     }
  562.  
  563.       /* Work out the safe way to copy */
  564.       if (dreg == ptrreg1)
  565.     {
  566.       /* Copy into the second half first */
  567.       return "mov.l    %R1,%R0\n\tmov.l    %1,%0 ! cr";
  568.     }
  569.     }
  570.  
  571.   return "mov.l    %1,%0\n\tmov.l    %R1,%R0";
  572. }
  573.  
  574. /* Emit assembly to shift reg by k bits */
  575.  
  576. char *
  577. output_shift (string, reg, k, code)
  578.      char *string;
  579.      rtx reg;
  580.      rtx k;
  581.      int code;
  582.  
  583. {
  584.   int s = INTVAL (k);
  585.  
  586.   if (code == ASHIFT && s == 31)
  587.     {
  588.       /* Shift left by 31 moving into the t bit, clearing and rotating the other way */
  589.  
  590.       fprintf (asm_out_file, "\trotr    r%d\n", REGNO (reg));
  591.       fprintf (asm_out_file, "\tmov    #0,r%d\n", REGNO (reg));
  592.       fprintf (asm_out_file, "\trotcr    r%d\n", REGNO (reg));
  593.       s = 0;
  594.     }
  595.  
  596.   if (code == LSHIFTRT && s == 31)
  597.     {
  598.       fprintf (asm_out_file, "\trotl    r%d\n", REGNO (reg));
  599.       fprintf (asm_out_file, "\tmov    #0,r%d\n", REGNO (reg));
  600.       fprintf (asm_out_file, "\trotcl    r%d\n", REGNO (reg));
  601.       s = 0;
  602.     }
  603.  
  604.   while (s)
  605.     {
  606.       char *out;
  607.       int d;
  608.  
  609.       if (s >= 16)
  610.     {
  611.       d = 16;
  612.       out = "16";
  613.     }
  614.       else if (s >= 8)
  615.     {
  616.       d = 8;
  617.       out = "8";
  618.     }
  619.       else if (s >= 2)
  620.     {
  621.       d = 2;
  622.       out = "2";
  623.     }
  624.       else
  625.     {
  626.       d = 1;
  627.       out = "";
  628.     }
  629.       fprintf (asm_out_file, "\t%s%s\tr%d\n", string, out, REGNO (reg));
  630.       s -= d;
  631.     }
  632.   return "";
  633. }
  634.  
  635. /* Return the text of the branch instruction which matches its length
  636.    attribute.
  637.  
  638.    This gets tricky if we have an insn in the delay slot of a branch
  639.    and the branch needs more than 1 insn to complete.*/
  640.  
  641.  
  642.  
  643. char *
  644. output_branch (logic, insn)
  645.      int logic;
  646.      rtx insn;
  647. {
  648.   extern rtx recog_operand[];
  649.   int label = lf++;
  650.   int rn = -1;
  651.   int need_save;
  652.  
  653.   switch (get_attr_length (insn))
  654.     {
  655.     case 2:
  656.       /* Simple branch in range -200..+200 bytes */
  657.       return logic ? "bt%.    %l0" : "bf%.    %l0";
  658.  
  659.     case 6:
  660.       /* Branch in range -4000..+4000 bytes */
  661.       {
  662.     rtx oldop = recog_operand[0];
  663.  
  664.  
  665.     if (need_slot (final_sequence))
  666.       {
  667.         fprintf (asm_out_file, "\tb%c.s\tLF%d\n", logic ? 'f' : 't',
  668.              label);
  669.  
  670.         print_slot (final_sequence);
  671.       }
  672.  
  673.     else
  674.       {
  675.         fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't',
  676.              label);
  677.       }
  678.     recog_operand[0] = oldop;
  679.  
  680.     output_asm_insn ("bra    %l0    ! 12 bit cond ", recog_operand);
  681.     fprintf (asm_out_file, "\tor    r0,r0\n");
  682.     label = dump_constants (label);
  683.     fprintf (asm_out_file, "LF%d:\n", label);
  684.       }
  685.  
  686.       return "";
  687.  
  688.     case 8:
  689.       /* Branches a long way away */
  690.       {
  691.  
  692.     rtx oldop = recog_operand[0];
  693.  
  694.     if (need_slot (final_sequence))
  695.       {
  696.         fprintf (asm_out_file, "\tb%c.s\tLF%d\n", logic ? 'f' : 't', label);
  697.         print_slot (final_sequence);
  698.  
  699.       }
  700.     else
  701.       {
  702.         fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
  703.       }
  704.  
  705.     recog_operand[0] = oldop;
  706.  
  707.     /* We use r13 as a scratch */
  708.     need_save = 0;
  709.     rn = 13;
  710.  
  711.     if (need_save)
  712.       fprintf (asm_out_file, "\tpush  r%d\n", rn);
  713.     fprintf (asm_out_file, "\tmov.l    LK%d,r%d\n", add_constant (oldop, SImode), rn);
  714.     fprintf (asm_out_file, "\tjmp    @r%d    ! 32 cond \n", rn);
  715.     if (need_save)
  716.       fprintf (asm_out_file, "\tpop  r%d\n", rn);
  717.     else
  718.       fprintf (asm_out_file, "\tor    r0,r0\n");
  719.     fprintf (asm_out_file, "LF%d:\n", label);
  720.     return "";
  721.       }
  722.     }
  723.   return "bad";
  724. }
  725.  
  726.  
  727. /* Predicates used by the templates */
  728.  
  729. /* Non zero if op is an immediate ok for a byte index */
  730.  
  731. int 
  732. byte_index_operand (op, mode)
  733.      rtx op;
  734.      enum machine_mode mode;
  735. {
  736.   return (GET_CODE (op) == CONST_INT
  737.       && INTVAL (op) >= 0 && INTVAL (op) <= 15);
  738. }
  739.  
  740. /* Non zero if OP is a pop operand */
  741.  
  742. int
  743. pop_operand (op, mode)
  744.      rtx op;
  745.      enum machine_mode mode;
  746. {
  747.   if (GET_CODE (op) != MEM)
  748.     return 0;
  749.  
  750.   if (GET_MODE (op) != mode)
  751.     return 0;
  752.  
  753.   op = XEXP (op, 0);
  754.  
  755.   if (GET_CODE (op) != POST_INC)
  756.     return 0;
  757.  
  758.   return XEXP (op, 0) == stack_pointer_rtx;
  759. }
  760.  
  761. /* Non zero if OP is an immediate which can be made from two insns. */
  762.  
  763. int
  764. painful_immediate_operand (op, mode)
  765.      rtx op;
  766.      enum machine_mode mode;
  767. {
  768.   if (GET_CODE (op) == CONST_INT)
  769.     {
  770.       int i = INTVAL (op);
  771.  
  772.       if (i > 127 && i < 255)
  773.     return 1;        /* two adds */
  774.     }
  775.   return 0;
  776. }
  777.  
  778.  
  779. /* Non zero if OP can be source of a simple move operation. */
  780.  
  781. int
  782. general_movsrc_operand (op, mode)
  783.      rtx op;
  784.      enum machine_mode mode;
  785. {
  786.   if (GET_CODE (op) == REG
  787.       || GET_CODE (op) == SUBREG
  788.       || (GET_CODE (op) == CONST_INT &&
  789.       CONST_OK_FOR_I (INTVAL (op)))
  790.       || GET_CODE (op) == MEM)
  791.     return general_operand (op, mode);
  792.   return 0;
  793. }
  794.  
  795.  
  796.  
  797. /* Nonzero if OP is a normal arithmetic register. */
  798.  
  799. int
  800. arith_reg_operand (op, mode)
  801.      rtx op;
  802.      enum machine_mode mode;
  803. {
  804.   if (register_operand (op, mode))
  805.     {
  806.       if (GET_CODE (op) == REG)
  807.     return REGNO (op) != T_REG;
  808.       return 1;
  809.     }
  810.   return 0;
  811. }
  812.  
  813.  
  814. /* Nonzero if OP is a valid source operand for an arithmetic insn.  */
  815.  
  816. int
  817. arith_operand (op, mode)
  818.      rtx op;
  819.      enum machine_mode mode;
  820. {
  821.   if (register_operand (op, mode))
  822.     return 1;
  823.  
  824.   if (GET_CODE (op) == CONST_INT)
  825.     {
  826.       if (CONST_OK_FOR_I (INTVAL (op)))
  827.     return 1;
  828.     }
  829.   return 0;
  830. }
  831.  
  832.  
  833. /* Nonzero if OP is a valid source operand for a logical operation */
  834.  
  835. int
  836. logical_operand (op, mode)
  837.      rtx op;
  838.      enum machine_mode mode;
  839. {
  840.   if (register_operand (op, mode))
  841.     return 1;
  842.  
  843.   if (GET_CODE (op) == CONST_INT)
  844.     {
  845.       if (CONST_OK_FOR_L (INTVAL (op)))
  846.     return 1;
  847.     }
  848.   return 0;
  849. }
  850.  
  851. /* Nonzero if p is a valid shift operand for lshr and ashl */
  852.  
  853. int
  854. ok_shift_value (p)
  855.      rtx p;
  856. {
  857.   if (GET_CODE (p) == CONST_INT)
  858.     {
  859.       switch (INTVAL (p))
  860.     {
  861.     case 1:
  862.     case 2:
  863.     case 8:
  864.     case 16:
  865.       return 1;
  866.     default:
  867.       if (TARGET_FASTCODE)
  868.         return INTVAL (p) >= 0;
  869.     }
  870.     }
  871.   return 0;
  872. }
  873.  
  874. /* Nonzero if the arg is an immediate which has to be loaded from
  875.    memory */
  876.  
  877. int
  878. hard_immediate_operand (op, mode)
  879.      rtx op;
  880.      enum machine_mode mode;
  881. {
  882.   if (immediate_operand (op, mode))
  883.     {
  884.       if (GET_CODE (op) == CONST_INT
  885.       && INTVAL (op) >= -128 && INTVAL (op) < 127)
  886.     return 0;
  887.       return 1;
  888.     }
  889.   return 0;
  890. }
  891.  
  892. /* The SH cannot load a large constant into a register, constants have to
  893.    come from a pc relative load.  The reference of a pc relative load
  894.    instruction must be less than 1k infront of the instruction.  This
  895.    means that we often have to dump a constant inside a function, and
  896.    generate code to branch around it.
  897.  
  898.    It is important to minimize this, since the branches will slow things
  899.    down and make things bigger.
  900.  
  901.   Worst case code looks like:
  902.  
  903.       mov.l L1,rn
  904.       bra   L2
  905.       nop
  906.       align
  907. L1:   .long value
  908. L2:
  909.       ..
  910.  
  911.       mov.l L3,rn
  912.       bra   L4
  913.       nop
  914.       align
  915. L3:   .long value
  916. L4:
  917.       ..
  918.  
  919.    During shorten_branches we notice the instructions which can have a
  920.    constant table in them, if we see two that are close enough
  921.    together, we move the constants from the first table to the second
  922.    table and continue.  This process can happen again and again, and
  923.    in the best case, moves the constant table outside of the function.
  924.  
  925.    In the above example, we can tell that L3 is within 1k of L1, so
  926.    the first move can be shrunk from the 3 insn+constant sequence into
  927.    just 1 insn, and the constant moved to L3 to make:
  928.  
  929.    mov.l    L1,rn
  930.    ..
  931.    mov.l    L3,rn
  932.    bra        L4
  933.    nop
  934.    align
  935. L3:.long value
  936. L4:.long value
  937.  
  938.    Then the second move becomes the target for the shortening process.
  939.  
  940.    We keep a simple list of all the constants accumulated in the
  941.    current pool so there are no duplicates in a single table, but
  942.    they are not factored into the size estimates.
  943.  
  944. */
  945.  
  946. typedef struct
  947. {
  948.   rtx value;
  949.   int number;
  950.   enum machine_mode mode;
  951. } pool_node;
  952.  
  953. /* The maximum number of constants that can fit into one pool, since
  954.    the pc relative range is 0...1020 bytes and constants are at least 4
  955.    bytes long */
  956.  
  957. #define MAX_POOL_SIZE (1020/4)
  958. static pool_node pool_vector[MAX_POOL_SIZE];
  959. static int pool_size;
  960.  
  961.  
  962. /* Add a constant to the pool and return its label number.  */
  963.  
  964. static int
  965. add_constant (x, mode)
  966.      rtx x;
  967.      enum machine_mode mode;
  968. {
  969.   int i;
  970.  
  971.   /* Start the countdown on the first constant */
  972.  
  973.   if (!pool_size)
  974.     {
  975.       first_pc = pc;
  976.     }
  977.  
  978.   /* First see if we've already got it */
  979.  
  980.   for (i = 0; i < pool_size; i++)
  981.     {
  982.  
  983.       if (x->code == pool_vector[i].value->code
  984.       && mode == pool_vector[i].mode)
  985.     {
  986.       if (x->code == CODE_LABEL)
  987.         {
  988.           if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
  989.         continue;
  990.         }
  991.     }
  992.  
  993.       if (rtx_equal_p (x, pool_vector[i].value))
  994.     return pool_vector[i].number;
  995.     }
  996.  
  997.  
  998.   pool_vector[pool_size].value = x;
  999.   pool_vector[pool_size].mode = mode;
  1000.   pool_vector[pool_size].number = lf;
  1001.   pool_size++;
  1002.  
  1003.   return lf++;
  1004. }
  1005.  
  1006. /* Nonzero if the insn could take a constant table.  */
  1007.  
  1008. static int
  1009. has_constant_table (insn)
  1010.      rtx insn;
  1011. {
  1012.   rtx body;
  1013.  
  1014.   if (GET_CODE (insn) == NOTE
  1015.       || GET_CODE (insn) == BARRIER
  1016.       || GET_CODE (insn) == CODE_LABEL)
  1017.     return 0;
  1018.  
  1019.   body = PATTERN (insn);
  1020.   if (GET_CODE (body) == SEQUENCE)
  1021.     return 0;
  1022.   if (GET_CODE (body) == ADDR_VEC)
  1023.     return 0;
  1024.   if (GET_CODE (body) == USE)
  1025.     return 0;
  1026.   if (GET_CODE (body) == CLOBBER)
  1027.     return 0;
  1028.   if (get_attr_constneed (insn) == CONSTNEED_YES)
  1029.     return 1;
  1030.  
  1031.   if (GET_CODE (body) == UNSPEC_VOLATILE)
  1032.     {
  1033.       return INTVAL (XVECEXP (body, 0, 0)) == 1;
  1034.     }
  1035.   return 0;
  1036. }
  1037.  
  1038. /*  Adjust the length of an instruction.
  1039.  
  1040.     We'll look at the previous instruction which holds a constant
  1041.     table and see if we can move the table to here instead. */
  1042.  
  1043. int target_insn_uid;
  1044. int target_insn_smallest_size;
  1045.  
  1046. int target_pc;
  1047. int target_insn_range;
  1048. int current_pc;
  1049. int pool_bytes;
  1050.  
  1051. int last_uid;
  1052. int last_pc;
  1053.  
  1054. void
  1055. adjust_insn_length (insn, insn_lengths)
  1056.      rtx insn;
  1057.      short *insn_lengths;
  1058. {
  1059.   int uid = INSN_UID (insn);
  1060.   rtx body = PATTERN (insn);
  1061.  
  1062.   current_pc += insn_lengths[uid];
  1063.  
  1064.  
  1065.   if (GET_CODE (body) == SEQUENCE)
  1066.     {
  1067.       int i;
  1068.  
  1069.       for (i = 0; i < XVECLEN (body, 0); i++)
  1070.     {
  1071.       adjust_insn_length (XVECEXP (body, 0, i), insn_lengths);
  1072.     }
  1073.     }
  1074.   else
  1075.     {
  1076.       if (has_constant_table (insn))
  1077.     {
  1078.       if (current_pc >= target_insn_range)
  1079.         {
  1080.           /* This instruction is further away from the referencing
  1081.            instruction than it can reach, so we'll stop accumulating
  1082.            from that one and start fresh. */
  1083.           target_pc = current_pc;
  1084.           target_insn_range = current_pc + MAYBE_DUMP_LEVEL;
  1085.         }
  1086.       else
  1087.         {
  1088.           /* This instruction is within the reach of the target,
  1089.            remove the constant table from the target by adjusting
  1090.            downwards, and increase the size of this one to
  1091.            compensate.  */
  1092.  
  1093.  
  1094.           /* Add the stuff from this insn to what will go in the
  1095.            growing table. */
  1096.  
  1097.           pool_bytes += get_attr_constantsize (insn);
  1098.  
  1099.           /* The target shinks to its smallest natural size */
  1100.           insn_lengths[target_insn_uid] = target_insn_smallest_size;
  1101.  
  1102.           /* The current insn grows to be its larger size plust the
  1103.            table size. */
  1104.  
  1105.           insn_lengths[uid] = get_attr_largestsize (insn) + pool_bytes;
  1106.  
  1107.         }
  1108.       /* Current insn becomes the target.  */
  1109.       target_insn_uid = uid;
  1110.       target_insn_smallest_size = get_attr_smallestsize (insn);
  1111.  
  1112.     }
  1113.     }
  1114. }
  1115.  
  1116.  
  1117.  
  1118. /* Dump out the pending constant pool.
  1119.    If label provided then insert an branch in the middle of the table
  1120.    */
  1121.  
  1122. int
  1123. dump_constants (label)
  1124. {
  1125.   int i;
  1126.   int rlabel = label;
  1127.   int size = 0;
  1128.  
  1129.   if (pool_size)
  1130.     {
  1131.       fprintf (asm_out_file, "\n\t! constants - waited %d\n", pc - first_pc);
  1132.       fprintf (asm_out_file, "\t.align\t2\n");
  1133.  
  1134.       for (i = 0; i < pool_size; i++)
  1135.     {
  1136.       pool_node *p = pool_vector + i;
  1137.  
  1138.       fprintf (asm_out_file, "LK%d:", p->number);
  1139.       size += GET_MODE_SIZE (p->mode);
  1140.  
  1141.       switch (GET_MODE_CLASS (p->mode))
  1142.         {
  1143.         case MODE_INT:
  1144.         case MODE_PARTIAL_INT:
  1145.           assemble_integer (p->value, GET_MODE_SIZE (p->mode), 1);
  1146.           break;
  1147.         case MODE_FLOAT:
  1148.           {
  1149.         union real_extract u;
  1150.         bcopy (&CONST_DOUBLE_LOW (p->value), &u, sizeof u);
  1151.         assemble_real (u.d, p->mode);
  1152.           }
  1153.         }
  1154.  
  1155.       /* After 200 bytes of table, stick in another branch */
  1156.       if (label && size > 200)
  1157.         {
  1158.           rlabel = lf++;
  1159.           fprintf (asm_out_file, "LF%d:\tbra    LF%d\n", label, rlabel);
  1160.           fprintf (asm_out_file, "\tor    r0,r0\n");
  1161.           label = 0;
  1162.         }
  1163.  
  1164.     }
  1165.     }
  1166.  
  1167.   pool_size = 0;
  1168.   current_pc = 0;
  1169.   pc = 0;
  1170.   pool_bytes = 0;
  1171.  
  1172.   target_insn_range = 0;
  1173.   return rlabel;
  1174.  
  1175. }
  1176.  
  1177.  
  1178. /* Emit the text to load a value from a constant table.  */
  1179.  
  1180. char *
  1181. output_movepcrel (insn, operands, mode)
  1182.      rtx insn;
  1183.      rtx operands[];
  1184.      enum machine_mode mode;
  1185. {
  1186.   int len = GET_MODE_SIZE (mode);
  1187.   int rn = REGNO (operands[0]);
  1188.  
  1189.   fprintf (asm_out_file, "\tmov.l    LK%d,r%d\n",
  1190.        add_constant (operands[1], mode), rn);
  1191.  
  1192.   if (GET_MODE_SIZE (mode) > 4)
  1193.     {
  1194.       fprintf (asm_out_file,
  1195.            "\tmov.l    LK%d+4,r%d\n",
  1196.            add_constant (operands[1], mode),
  1197.            rn + 1);
  1198.  
  1199.     }
  1200.  
  1201.   /* This may have been the last move in the function, so nothing
  1202.      took its constant table, we may be able to move it past the end
  1203.      of the function (after the rts) if we are careful */
  1204.  
  1205.   if (target_insn_uid == INSN_UID (insn)
  1206.       && current_pc < target_insn_range)
  1207.     return "";
  1208.  
  1209.  
  1210.   /* If this instruction is as small as it can be, there can be no
  1211.      constant table attached to it.  */
  1212.   if (get_attr_length (insn) != get_attr_smallestsize (insn))
  1213.     {
  1214.       /* This needs a constant table */
  1215.       fprintf (asm_out_file, "\t!constant table start\n");
  1216.       fprintf (asm_out_file, "\tbra    LF%d\n", lf);
  1217.       fprintf (asm_out_file, "\tor    r0,r0 ! wasted slot\n");
  1218.       dump_constants (0);
  1219.       fprintf (asm_out_file, "LF%d:\n", lf++);
  1220.       fprintf (asm_out_file, "\t!constant table end\n");
  1221.     }
  1222.   return "";
  1223. }
  1224.  
  1225.  
  1226. /* Dump out interesting debug info */
  1227.  
  1228. rtx
  1229. final_prescan_insn (insn, opvec, noperands)
  1230.      rtx insn;
  1231.      rtx *opvec;
  1232.      int noperands;
  1233. {
  1234.   register rtx body = PATTERN (insn);
  1235.  
  1236.   if (target_flags & ISIZE_BIT)
  1237.     {
  1238.       extern int *insn_addresses;
  1239.  
  1240.       fprintf (asm_out_file, "\n!%04x*\n",
  1241.            insn_addresses[INSN_UID (insn)] + 0x10);
  1242.  
  1243.       fprintf (asm_out_file, "\n!%04x %d %04x len=%d\n",
  1244.            pc, pool_size, first_pc, get_attr_length (insn));
  1245.  
  1246.       if (TARGET_DUMP_RTL)
  1247.     print_rtl (asm_out_file, body);
  1248.  
  1249.  
  1250.     }
  1251.  
  1252.   pc += get_attr_length (insn);
  1253.   if (pool_size && pc - first_pc > MUST_DUMP_LEVEL)
  1254.     {
  1255.       /* For some reason we have not dumped out a constant table, and
  1256.      we have emitted a lot of code.  This can happen if the think
  1257.      which wants the table is a long conditional branch (which has no
  1258.      room for a constant table), and there has not been a move
  1259.      constant anywhere. */
  1260.       int label = lf++;
  1261.       fprintf (asm_out_file, "\t!forced constant table\n");
  1262.       fprintf (asm_out_file, "\tbra    LF%d\n", label);
  1263.       fprintf (asm_out_file, "\tor    r0,r0 ! wasted slot\n");
  1264.       label = dump_constants (label);
  1265.       fprintf (asm_out_file, "LF%d:\n", label);
  1266.       fprintf (asm_out_file, "\t!constant table end\n");
  1267.     }
  1268. }
  1269.  
  1270.  
  1271.  
  1272. /* Block move stuff stolen from m88k*/
  1273.  
  1274. /* Emit code to perform a block move.  Choose the best method.
  1275.  
  1276.    OPERANDS[0] is the destination.
  1277.    OPERANDS[1] is the source.
  1278.    OPERANDS[2] is the size.
  1279.    OPERANDS[3] is the alignment safe to use.  */
  1280.  
  1281. /* Emit code to perform a block move with an offset sequence of ld/st
  1282.    instructions (..., ld 0, st 1, ld 1, st 0, ...).  SIZE and ALIGN are
  1283.    known constants.  DEST and SRC are registers.  OFFSET is the known
  1284.    starting point for the output pattern.  */
  1285.  
  1286. static enum machine_mode mode_from_align[] =
  1287. {VOIDmode, QImode, HImode, VOIDmode, SImode,
  1288.  VOIDmode, VOIDmode, VOIDmode, DImode};
  1289. static void
  1290.  
  1291. block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
  1292.      rtx dest, dest_mem;
  1293.      rtx src, src_mem;
  1294.      int size;
  1295.      int align;
  1296.      int offset;
  1297. {
  1298.   rtx temp[2];
  1299.   enum machine_mode mode[2];
  1300.   int amount[2];
  1301.   int active[2];
  1302.   int phase = 0;
  1303.   int next;
  1304.   int offset_ld = offset;
  1305.   int offset_st = offset;
  1306.  
  1307.   active[0] = active[1] = FALSE;
  1308.  
  1309.   /* Establish parameters for the first load and for the second load if
  1310.      it is known to be the same mode as the first.  */
  1311.   amount[0] = amount[1] = align;
  1312.  
  1313.  
  1314.   mode[0] = mode_from_align[align];
  1315.  
  1316.   temp[0] = gen_reg_rtx (mode[0]);
  1317.   if (size >= 2 * align)
  1318.     {
  1319.       mode[1] = mode[0];
  1320.       temp[1] = gen_reg_rtx (mode[1]);
  1321.     }
  1322.  
  1323.   do
  1324.     {
  1325.       rtx srcp, dstp;
  1326.       next = phase;
  1327.       phase = !phase;
  1328.  
  1329.       if (size > 0)
  1330.     {
  1331.       /* Change modes as the sequence tails off.  */
  1332.       if (size < amount[next])
  1333.         {
  1334.           amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
  1335.           mode[next] = mode_from_align[amount[next]];
  1336.           temp[next] = gen_reg_rtx (mode[next]);
  1337.         }
  1338.       size -= amount[next];
  1339.       srcp = gen_rtx (MEM,
  1340.               MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
  1341.               gen_rtx (PLUS, Pmode, src,
  1342.                    gen_rtx (CONST_INT, SImode, offset_ld)));
  1343.       RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
  1344.       MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
  1345.       MEM_IN_STRUCT_P (srcp) = 1;
  1346.       emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp));
  1347.       offset_ld += amount[next];
  1348.       active[next] = TRUE;
  1349.     }
  1350.  
  1351.       if (active[phase])
  1352.     {
  1353.       active[phase] = FALSE;
  1354.       dstp = gen_rtx (MEM,
  1355.               MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
  1356.               gen_rtx (PLUS, Pmode, dest,
  1357.                    gen_rtx (CONST_INT, SImode, offset_st)));
  1358.       RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
  1359.       MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
  1360.       MEM_IN_STRUCT_P (dstp) = 1;
  1361.       emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase]));
  1362.       offset_st += amount[phase];
  1363.     }
  1364.     }
  1365.   while (active[next]);
  1366. }
  1367.  
  1368. void
  1369. expand_block_move (dest_mem, src_mem, operands)
  1370.      rtx dest_mem;
  1371.      rtx src_mem;
  1372.      rtx *operands;
  1373. {
  1374.   int align = INTVAL (operands[3]);
  1375.   int constp = (GET_CODE (operands[2]) == CONST_INT);
  1376.   int bytes = (constp ? INTVAL (operands[2]) : 0);
  1377.  
  1378. #if 0
  1379.   if (constp && bytes <= 0)
  1380.     return;
  1381.  
  1382.   if (align > 4)
  1383.     align = 4;
  1384.  
  1385.   if (constp && bytes <= 3 * align)
  1386.     block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
  1387.              bytes, align, 0);
  1388.  
  1389. #if 0
  1390.   else if (constp && bytes <= best_from_align[target][align])
  1391.     block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
  1392.             bytes, align);
  1393.  
  1394.   else if (constp && align == 4 && TARGET_88100)
  1395.     block_move_loop (operands[0], dest_mem, operands[1], src_mem,
  1396.              bytes, align);
  1397. #endif
  1398.   else
  1399. #endif
  1400.     {
  1401.       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
  1402.              VOIDmode, 3,
  1403.              operands[0], Pmode,
  1404.              operands[1], Pmode,
  1405.              operands[2], SImode);
  1406.     }
  1407. }
  1408.  
  1409.  
  1410. override_options ()
  1411. {
  1412.   sh_cpu = CPU_SH0;
  1413.   if (TARGET_SH1)
  1414.     sh_cpu = CPU_SH1;
  1415.   if (TARGET_SH2)
  1416.     sh_cpu = CPU_SH2;
  1417.   if (TARGET_SH3)
  1418.     sh_cpu = CPU_SH3;
  1419. }
  1420.  
  1421.  
  1422. /* Stuff taken from m88k.c */
  1423.  
  1424. /* Output to FILE the start of the assembler file.  */
  1425.  
  1426. struct option
  1427. {
  1428.   char *string;
  1429.   int *variable;
  1430.   int on_value;
  1431. };
  1432.  
  1433. static int
  1434. output_option (file, sep, type, name, indent, pos, max)
  1435.      FILE *file;
  1436.      char *sep;
  1437.      char *type;
  1438.      char *name;
  1439.      char *indent;
  1440.      int pos;
  1441.      int max;
  1442. {
  1443.   if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
  1444.     {
  1445.       fprintf (file, indent);
  1446.       return fprintf (file, "%s%s", type, name);
  1447.     }
  1448.   return pos + fprintf (file, "%s%s%s", sep, type, name);
  1449. }
  1450.  
  1451. static struct
  1452.   {
  1453.     char *name;
  1454.     int value;
  1455.   }
  1456.  
  1457. m_options[] = TARGET_SWITCHES;
  1458.  
  1459. static void
  1460. output_options (file, f_options, f_len, W_options, W_len,
  1461.         pos, max, sep, indent, term)
  1462.      FILE *file;
  1463.      struct option *f_options;
  1464.      struct option *W_options;
  1465.      int f_len, W_len;
  1466.      int pos;
  1467.      int max;
  1468.      char *sep;
  1469.      char *indent;
  1470.      char *term;
  1471. {
  1472.   register int j;
  1473.  
  1474.  
  1475.   if (optimize)
  1476.     pos = output_option (file, sep, "-O", "", indent, pos, max);
  1477.   if (write_symbols != NO_DEBUG)
  1478.     pos = output_option (file, sep, "-g", "", indent, pos, max);
  1479.   if (flag_traditional)
  1480.     pos = output_option (file, sep, "-traditional", "", indent, pos, max);
  1481.   if (profile_flag)
  1482.     pos = output_option (file, sep, "-p", "", indent, pos, max);
  1483.   if (profile_block_flag)
  1484.     pos = output_option (file, sep, "-a", "", indent, pos, max);
  1485.  
  1486.   for (j = 0; j < f_len; j++)
  1487.     if (*f_options[j].variable == f_options[j].on_value)
  1488.       pos = output_option (file, sep, "-f", f_options[j].string,
  1489.                indent, pos, max);
  1490.  
  1491.   for (j = 0; j < W_len; j++)
  1492.     if (*W_options[j].variable == W_options[j].on_value)
  1493.       pos = output_option (file, sep, "-W", W_options[j].string,
  1494.                indent, pos, max);
  1495.  
  1496.   for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
  1497.     if (m_options[j].name[0] != '\0'
  1498.     && m_options[j].value > 0
  1499.     && ((m_options[j].value & target_flags)
  1500.         == m_options[j].value))
  1501.       pos = output_option (file, sep, "-m", m_options[j].name,
  1502.                indent, pos, max);
  1503.  
  1504.  
  1505.   fprintf (file, term);
  1506. }
  1507.  
  1508. void
  1509. output_file_start (file, f_options, f_len, W_options, W_len)
  1510.      FILE *file;
  1511.      struct option *f_options;
  1512.      struct option *W_options;
  1513.      int f_len, W_len;
  1514. {
  1515.   register int pos;
  1516.  
  1517.   output_file_directive (file, main_input_filename);
  1518.  
  1519.   /* Switch to the data section so that the coffsem symbol and the
  1520.      gcc2_compiled. symbol aren't in the text section.  */
  1521.   data_section ();
  1522.  
  1523.  
  1524.   pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string);
  1525.   output_options (file, f_options, f_len, W_options, W_len,
  1526.           pos, 75, " ", "\n! ", "\n\n");
  1527. }
  1528.  
  1529.  
  1530. /* Code to generate prologue and epilogue sequences */
  1531.  
  1532. void
  1533. sh_expand_prologue ()
  1534. {
  1535.   int live_regs_mask;
  1536.   int d;
  1537.  
  1538.   live_regs_mask = calc_live_regs (&d);
  1539.  
  1540.   output_stack_adjust (-1, current_function_pretend_args_size);
  1541.  
  1542.   if (current_function_anonymous_args)
  1543.     {
  1544.       /* Push arg regs as if they'd been provided by caller in stack */
  1545.       int i;
  1546.       for (i = 0; i < NPARM_REGS; i++)
  1547.     {
  1548.       int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
  1549.       if (i > NPARM_REGS - current_function_args_info)
  1550.         break;
  1551.       push (rn);
  1552.  
  1553.       extra_push += 4;
  1554.     }
  1555.     }
  1556.  
  1557.   if (frame_pointer_needed)
  1558.     {
  1559.       push_regs (live_regs_mask);
  1560.       emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
  1561.     }
  1562.   else
  1563.     {
  1564.       push_regs (live_regs_mask);
  1565.     }
  1566.  
  1567.   output_stack_adjust (-1, get_frame_size ());
  1568. }
  1569.  
  1570. void
  1571. sh_expand_epilogue ()
  1572. {
  1573.   int live_regs_mask;
  1574.   int d;
  1575.   int i;
  1576.  
  1577.   live_regs_mask = calc_live_regs (&d);
  1578.  
  1579.   if (frame_pointer_needed)
  1580.     {
  1581.       emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
  1582.     }
  1583.   else
  1584.     {
  1585.       output_stack_adjust (1, get_frame_size ());
  1586.     }
  1587.  
  1588.  
  1589.   /* Pop all the registers */
  1590.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  1591.     {
  1592.       int j = (FIRST_PSEUDO_REGISTER - 1) - i;
  1593.       if (live_regs_mask & (1 << j))
  1594.     {
  1595.       pop (j);
  1596.     }
  1597.     }
  1598.   output_stack_adjust (1, extra_push +
  1599.                current_function_pretend_args_size);
  1600.  
  1601.   extra_push = 0;
  1602.  
  1603.   current_function_anonymous_args = 0;
  1604. }
  1605.  
  1606.  
  1607. /* Return the cost of a shift */
  1608.  
  1609. int
  1610. shiftcosts (RTX)
  1611.      rtx RTX;
  1612. {
  1613.   /* If shift by a non constant, then this will be expensive. */
  1614.   if (GET_CODE (XEXP (RTX, 1)) != CONST_INT)
  1615.     return 20;
  1616.  
  1617.   /* otherwise, it will be very cheap if by one of the constants
  1618.      we can cope with. */
  1619.   if (CONST_OK_FOR_K (INTVAL (XEXP (RTX, 1))))
  1620.     return 1;
  1621.  
  1622.   /* otherwise it will be several insns. */
  1623.   return 4;
  1624. }
  1625.  
  1626. /* Return the cost of a multiply */
  1627. int
  1628. multcosts (RTX)
  1629.      rtx RTX;
  1630. {
  1631.   /* If we we're aiming at small code, then just count the number of
  1632.      insns in a multiply call sequence, otherwise, count all the insnsn
  1633.      inside the call. */
  1634.   if (TARGET_SMALLCODE)
  1635.     return 3;
  1636.   return 30;
  1637. }
  1638.